package bb.lanxing.model.map;

import android.os.Parcel;
import android.os.Parcelable;

import com.github.mikephil.charting.utils.Utils;

import bb.lanxing.lib.kt.model.geo.IGeoPoint;
import bb.lanxing.util.map.GeoCoorConverter;

public class GeoPoint implements IGeoPoint {
    public static final Parcelable.Creator<GeoPoint> CREATOR = new Parcelable.Creator<GeoPoint>() {
        @Override
        public GeoPoint createFromParcel(Parcel source) {
            return new GeoPoint(source);
        }

        @Override
        public GeoPoint[] newArray(int size) {
            return new GeoPoint[size];
        }
    };
    private double altitude = Utils.DOUBLE_EPSILON;
    private double latitude;
    private double longitude;
    private int type;

    @Override
    public int describeContents() {
        return 0;
    }

    public GeoPoint(int type, double latitude, double longitude) {
        this.type = type;
        this.latitude = latitude;
        this.longitude = longitude;
    }

    public static GeoPoint fromBaidu(double latitude, double longitude) {
        return new GeoPoint(TYPE_BAIDU, latitude, longitude);//2
    }

    public static GeoPoint fromEarth(double latitude, double longitude) {
        return new GeoPoint(TYPE_EARTH, latitude, longitude);//0
    }

    public static GeoPoint fromCommon(double latitude, double longitude) {
        return new GeoPoint(TYPE_COMMON, latitude, longitude);//1
    }

    @Override
    public IGeoPoint toBaidu() {
        return toBaidu(false);
    }

    @Override
    public IGeoPoint toCommon() {
        return toCommon(false);
    }

    @Override
    public IGeoPoint toEarth() {
        return toEarth(false);
    }

    @Override
    public IGeoPoint toBaidu(boolean create) {
        IGeoPoint earth2Baidu;
        int i = this.type;
        if (i == TYPE_BAIDU) {//2
            earth2Baidu = this;
        } else if (i == TYPE_COMMON) {//1
            earth2Baidu = GeoCoorConverter.common2Baidu(this);
        } else if (i == TYPE_EARTH) {//0
            earth2Baidu = GeoCoorConverter.earth2Baidu(this);
        } else {
            throw new IllegalArgumentException("illegal geo point type :" + this.type);
        }
        return (earth2Baidu == this && create) ? fromBaidu(earth2Baidu.getLatitude(), earth2Baidu.getLongitude()) : earth2Baidu;
    }

    @Override
    public IGeoPoint toCommon(boolean create) {
        IGeoPoint earth2Common;
        int i = this.type;
        if (i == TYPE_BAIDU) {
            earth2Common = GeoCoorConverter.baidu2Common(this);
        } else if (i == TYPE_COMMON) {
            earth2Common = this;
        } else if (i == TYPE_EARTH) {//0
            earth2Common = GeoCoorConverter.earth2Common(this);
        } else {
            throw new IllegalArgumentException("illegal geo point type :" + this.type);
        }
        return (earth2Common == this && create) ? fromCommon(earth2Common.getLatitude(), earth2Common.getLongitude()) : earth2Common;
    }

    @Override
    public IGeoPoint toEarth(boolean create) {
        IGeoPoint iGeoPoint;
        int i = this.type;
        if (i == TYPE_BAIDU) {
            iGeoPoint = GeoCoorConverter.baidu2Earth(this);
        } else if (i == TYPE_COMMON) {
            iGeoPoint = GeoCoorConverter.common2Earth(this);
        } else if (i != TYPE_EARTH) {
            throw new IllegalArgumentException("illegal geo point type :" + this.type);
        } else {
            iGeoPoint = this;
        }
        return (iGeoPoint == this && create) ? fromEarth(iGeoPoint.getLatitude(), iGeoPoint.getLongitude()) : iGeoPoint;
    }

    @Override
    public IGeoPoint toType(int type) {
        if (type != TYPE_EARTH) {
            if (type != TYPE_COMMON) {
                return type != TYPE_BAIDU ? this : toBaidu(false);
            }
            return toCommon(false);
        }
        return toEarth(false);
    }

    public IGeoPoint reuse(double latitude, double longitude) {
        this.latitude = latitude;
        this.longitude = longitude;
        return this;
    }

    @Override
    public int getType() {
        return this.type;
    }

    @Override
    public double getLatitude() {
        return this.latitude;
    }

    @Override
    public double getLongitude() {
        return this.longitude;
    }

    @Override
    public void setAltitude(double altitude) {
        this.altitude = altitude;
    }

    @Override
    public double getAltitude() {
        return this.altitude;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(this.type);
        dest.writeDouble(this.latitude);
        dest.writeDouble(this.longitude);
    }

    protected GeoPoint(Parcel in2) {
        this.type = in2.readInt();
        this.latitude = in2.readDouble();
        this.longitude = in2.readDouble();
    }
}